package petrochina.company.electric.ui.dialog;

import static com.inuker.bluetooth.library.Constants.REQUEST_SUCCESS;
import static com.inuker.bluetooth.library.Constants.STATUS_CONNECTED;

import android.content.Context;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;

import com.hjq.base.BaseDialog;
import com.hjq.toast.ToastUtils;
import com.inuker.bluetooth.library.connect.listener.BleConnectStatusListener;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.connect.response.BleNotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleReadResponse;
import com.inuker.bluetooth.library.connect.response.BleUnnotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleWriteResponse;
import com.inuker.bluetooth.library.model.BleGattCharacter;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.model.BleGattService;
import com.inuker.bluetooth.library.utils.BluetoothLog;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import petrochina.company.electric.R;
import petrochina.company.electric.aop.SingleClick;
import petrochina.company.electric.http.api.BleDeviceListApi;
import petrochina.company.electric.http.api.TaskDetailStepApi;
import petrochina.company.electric.manager.ClientManager;
import petrochina.company.electric.model.DetailItem;

/**
 * 优特蓝牙设备连接 操作
 */
public final class BleDeviceOptionDialog {

    public static final class Builder
            extends BaseDialog.Builder<Builder>
            implements
            View.OnLayoutChangeListener, Runnable {

        @SuppressWarnings("rawtypes")
        @Nullable
        private OnListener mListener;
        private boolean mAutoDismiss = true;

        private boolean mConnected;

        private UUID mService;
        private UUID mCharacter;

        private final LinearLayout mLockStatusView;
        private final AppCompatButton mBleOptStatusButton, mBtnBleOptCancel, mBtnBleOptReconnect;
        private final AppCompatImageView mIvBleLockOptStatus;
        private final AppCompatTextView mTvBleDeviceId;
        private final TextView mTvBleLockOptStatus, mTvBleDeviceName, mTvBleDeviceStatus, mTvBleDeviceStatusCurrent;

        private BleDeviceListApi.Bean mBleDevice;
        private TaskDetailStepApi.Bean mTaskPowerResult;
        private String stepStatus;


        public Builder(Context context) {
            super(context);
            initData();
            setContentView(R.layout.ble_devices_option_dialog);
            setAnimStyle(BaseDialog.ANIM_BOTTOM);
            mLockStatusView = findViewById(R.id.ll_lock_status);
            mIvBleLockOptStatus = findViewById(R.id.iv_ble_lock_opt_status);
            mTvBleLockOptStatus = findViewById(R.id.tv_ble_lock_opt_status);
            mBleOptStatusButton = findViewById(R.id.btn_ble_opt_status);
            mBtnBleOptCancel = findViewById(R.id.btn_ble_opt_cancel);
            mBtnBleOptReconnect = findViewById(R.id.btn_ble_opt_reconnect);
            mTvBleDeviceName = findViewById(R.id.tv_ble_device_name);
            mTvBleDeviceId = findViewById(R.id.tv_ble_device_id);
            mTvBleDeviceStatus = findViewById(R.id.tv_ble_device_status);
            mTvBleDeviceStatusCurrent = findViewById(R.id.tv_ble_device_status_current);
            setOnClickListener(mLockStatusView, mBleOptStatusButton, mBtnBleOptCancel, mBtnBleOptReconnect);

        }

        @Override
        public void show() {
            super.show();
            if (mTaskPowerResult != null) {
                mTvBleDeviceName.setText(mTaskPowerResult.getEquipType() == 3 ? "电阻检测仪ETCR2800" : "ETCR1840防水型近电报警器");
                if (mTaskPowerResult.getEquipType() == 3) {
                    if (!TextUtils.isEmpty(mTaskPowerResult.getEquipValue())) {
                        mTvBleDeviceStatus.setText("预期电阻值：" + mTaskPowerResult.getEquipValue() + "欧姆");
                    }
                }else{
                    mTvBleDeviceStatus.setText("预期带电状态：" + (mTaskPowerResult.getOperType() == 3 ? "带电" : "不带电"));
                }
            }
            if (mBleDevice != null) {
                mTvBleDeviceId.setText("编号：" + mBleDevice.getCode());
                ClientManager.getClient().registerConnectStatusListener(mBleDevice.getBluetookthAddress(), mConnectStatusListener);
                connectDeviceIfNeeded();
            } else {
                dismiss();
            }
        }

        private void connectDeviceIfNeeded() {
            if (!mConnected) {
                connectDevice();
            }
        }

        private final BleConnectStatusListener mConnectStatusListener = new BleConnectStatusListener() {
            @Override
            public void onConnectStatusChanged(String mac, int status) {
                BluetoothLog.v(String.format("DeviceDetailActivity onConnectStatusChanged %d in %s",
                        status, Thread.currentThread().getName()));

                mConnected = (status == STATUS_CONNECTED);
                connectDeviceIfNeeded();
            }
        };

        private void connectDevice() {
            BleConnectOptions options = new BleConnectOptions.Builder()
                    .setConnectRetry(3)
                    .setConnectTimeout(20000)
                    .setServiceDiscoverRetry(3)
                    .setServiceDiscoverTimeout(10000)
                    .build();
            ClientManager.getClient().connect(mBleDevice.getBluetookthAddress(), options, new BleConnectResponse() {
                @Override
                public void onResponse(int code, BleGattProfile profile) {
                    BluetoothLog.v(String.format("profile:\n%s", profile));
//                        mTvTitle.setText(String.format("%s", mDevice.getAddress()));
//                        mPbar.setVisibility(View.GONE);
//                        mListView.setVisibility(View.VISIBLE);

                    if (code == REQUEST_SUCCESS) {
                        mIvBleLockOptStatus.setImageResource(R.drawable.ble_connected_ic);

                        List<DetailItem> items = new ArrayList<DetailItem>();

                        List<BleGattService> services = profile.getServices();

                        for (BleGattService service : services) {
//                            items.add(new DetailItem(DetailItem.TYPE_SERVICE, service.getUUID(), null));
                            List<BleGattCharacter> characters = service.getCharacters();
                            for (BleGattCharacter character : characters) {
                                items.add(new DetailItem(DetailItem.TYPE_CHARACTER, character.getUuid(), service.getUUID()));
                            }
                        }
//                            mAdapter.setGattProfile(profile);
                        mTvBleLockOptStatus.setText("蓝牙连接成功");
                        if (items.size() > 1) {
                            mService = items.get(0).service;
                            mCharacter = items.get(0).uuid;
                        }

                        ClientManager.getClient().notify(mBleDevice.getBluetookthAddress(), items.get(0).service, items.get(0).uuid, mNotifyRsp);
                    } else {
                        mIvBleLockOptStatus.setImageResource(R.drawable.ble_disconnected_ic);
                        mTvBleLockOptStatus.setText("蓝牙断开连接");
                    }
                }
            });
        }

        private final BleReadResponse mReadRsp = new BleReadResponse() {
            @Override
            public void onResponse(int code, byte[] data) {
                if (code == REQUEST_SUCCESS) {
                    String hexString = bytesToHexString(data);
                    ToastUtils.show("read " + hexString);
//                    mBtnRead.setText(String.format("read: %s", ByteUtils.byteToString(data)));
//                    ToastUtils.show("read success "+ String.format("read: %s", ByteUtils.byteToString(data)));
                } else {
//                    ToastUtils.show("read failed");
//                    mBtnRead.setText("read");
                }
            }
        };

        private final BleWriteResponse mWriteRsp = new BleWriteResponse() {
            @Override
            public void onResponse(int code) {
                if (code == REQUEST_SUCCESS) {
//                    ToastUtils.show("write success");
                } else {
//                    ToastUtils.show("write failed");
                }
            }
        };

        private final BleNotifyResponse mNotifyRsp = new BleNotifyResponse() {
            @Override
            public void onNotify(UUID service, UUID character, byte[] value) {
                if (service.equals(mService) && character.equals(mCharacter)) {
                    String hexString = bytesToHexString(value);
                    if (hexString == null || TextUtils.isEmpty(hexString)) {
                        return;
                    }
                    int start = 6;
                    mTvBleDeviceStatus.setVisibility(View.VISIBLE);
                    if (mTaskPowerResult.getEquipType() == 3) {
                        mTvBleDeviceStatus.setText("预期电阻值：" + mTaskPowerResult.getEquipValue() + "欧姆");
                        // 电阻检测仪
                        if (hexString.length() > start) {
                            String a = hexString.substring(4, 6);
                            int index = Integer.parseInt(a, 16) * 2 + start;
                            index = Math.min(index, hexString.length());
                            String resistance = hexString.substring(start, index).toUpperCase();
//                            for (int i = start; i < index; i++) {
//                                valueBuffer.append(value[i]);
//                            }
                            int resistanceValue = Integer.parseInt(resistance, 16);
                            int realResistanceValue = resistanceValue / 100;
                            stepStatus = realResistanceValue + "";
                            // to do 方便测试逻辑
//                            mTaskPowerResult.setEquipValue("500");
                            mTvBleDeviceStatus.setTextColor(getResources().getColor(R.color.black));
                            if (resistanceValue == 50000 || (!TextUtils.isEmpty(mTaskPowerResult.getEquipValue()) && realResistanceValue > Double.parseDouble(mTaskPowerResult.getEquipValue()))) {

                                mTvBleDeviceStatusCurrent.setTextColor(getResources().getColor(R.color.red));
                                mBtnBleOptCancel.setVisibility(View.VISIBLE);
                                mBtnBleOptReconnect.setVisibility(View.VISIBLE);
                                mBleOptStatusButton.setVisibility(View.GONE);
                                // 比对失败上传统计
                                if (mListener == null) {
                                    return;
                                }
                                mListener.onSelected(getDialog(), 1, realResistanceValue);
                            } else {
//                                mTvBleDeviceStatus.setTextColor(getResources().getColor(R.color.red));
                                mTvBleDeviceStatusCurrent.setTextColor(getResources().getColor(R.color.common_confirm_text_color));
                                mBtnBleOptCancel.setVisibility(View.GONE);
                                mBtnBleOptReconnect.setVisibility(View.GONE);
                                mBleOptStatusButton.setVisibility(View.VISIBLE);
                            }

                            mTvBleDeviceStatusCurrent.setText("当前电阻值：" + (resistanceValue == 50000 ? stepStatus : "无穷大") + "欧姆");
                        }
                    } else {
                        // 验电棒
                        if ("01030200017984".equals(hexString)) {
                            mTvBleDeviceStatusCurrent.setText("实际带电状态：带电");
                            stepStatus = "带电";
                        } else if ("0103020000B844".equals(hexString) || "0103020000b844".equals(hexString)) {
                            mTvBleDeviceStatusCurrent.setText("实际带电状态：不带电");
                            stepStatus = "不带电";
                        }
                        boolean stepStatus = false;
                        if (mTaskPowerResult.getOperType() == 3) {
                            stepStatus = "实际带电状态：带电".equals(mTvBleDeviceStatusCurrent.getText().toString());
                        } else if (mTaskPowerResult.getOperType() == 4) {
                            stepStatus = "实际带电状态：不带电".equals(mTvBleDeviceStatusCurrent.getText().toString());
                        }
//                        if (stepStatus) {
//                            mTvBleDeviceStatus.setTextColor(getResources().getColor(R.color.black));
//                            mTvBleDeviceStatusCurrent.setTextColor(getResources().getColor(R.color.common_confirm_text_color));
//                        }
                        mTvBleDeviceStatus.setTextColor(getResources().getColor(R.color.black));
                        if (!stepStatus) {
                            mTvBleDeviceStatusCurrent.setTextColor(getResources().getColor(R.color.red));
                            mBtnBleOptCancel.setVisibility(View.VISIBLE);
                            mBtnBleOptReconnect.setVisibility(View.VISIBLE);
                            mBleOptStatusButton.setVisibility(View.GONE);
                            // 比对失败上传统计
                            if (mListener == null) {
                                return;
                            }
                            mListener.onSelected(getDialog(), 1, 0);
                        } else {
                            mTvBleDeviceStatusCurrent.setTextColor(getResources().getColor(R.color.common_confirm_text_color));
                            mBtnBleOptCancel.setVisibility(View.GONE);
                            mBtnBleOptReconnect.setVisibility(View.GONE);
                            mBleOptStatusButton.setVisibility(View.VISIBLE);
                        }
                    }
                }
            }

            @Override
            public void onResponse(int code) {
                if (code == REQUEST_SUCCESS) {
                    writeForBleToDevices();
//                    ClientManager.getClient().read(mBleDevice.getAddress(), mService, mCharacter, mReadRsp);
                } else {
//                    ToastUtils.show("notify failed");
                }
            }
        };

        private final BleUnnotifyResponse mUnnotifyRsp = new BleUnnotifyResponse() {
            @Override
            public void onResponse(int code) {
                if (code == REQUEST_SUCCESS) {
//                    ToastUtils.show("Unnotify success");
//                    mBtnNotify.setEnabled(true);
//                    mBtnUnnotify.setEnabled(false);
                } else {
//                    ToastUtils.show("Unnotify failed");
                }
            }
        };

        private void writeForBleToDevices() {
            byte[] value = null;
            if (mTaskPowerResult != null) {
                if (mTaskPowerResult.getEquipType() == 2) {
                    value = new byte[8];
                    value[0] = (byte) 0x01;
                    value[1] = (byte) 0x03;
                    value[2] = (byte) 0x00;
                    value[3] = (byte) 0x06;
                    value[4] = (byte) 0x00;
                    value[5] = (byte) 0x01;
                    value[6] = (byte) 0x64;
                    value[7] = (byte) 0x0B;
                } else if (mTaskPowerResult.getEquipType() == 3) {
                    value = new byte[8];
                    value[0] = (byte) 0x01;
                    value[1] = (byte) 0x03;
                    value[2] = (byte) 0x00;
                    value[3] = (byte) 0x01;
                    value[4] = (byte) 0x00;
                    value[5] = (byte) 0x01;
                    value[6] = (byte) 0xD5;
                    value[7] = (byte) 0xCA;
                }
            }
            // 读取报警状态
//                    String put = "010300060001640B";
//                    String newPut = stringToHexString(put);
//                    byte[] writes = getWriteData();
//                    byte[] value = new byte[8];
//                    value[0] = (byte) 0x01;
//                    value[1] = (byte) 0x03;
//                    value[2] = (byte) 0x00;
//                    value[3] = (byte) 0x06;
//                    value[4] = (byte) 0x00;
//                    value[5] = (byte) 0x01;
//                    value[6] = (byte) 0x64;
//                    value[7] = (byte) 0x0B;
            // 读取电阻值
//            byte[] value = new byte[8];
//            value[0] = (byte) 0x01;
//            value[1] = (byte) 0x03;
//            value[2] = (byte) 0x00;
//            value[3] = (byte) 0x01;
//            value[4] = (byte) 0x00;
//            value[5] = (byte) 0x01;
//            value[6] = (byte) 0xD5;
//            value[7] = (byte) 0xCA;
            // 设置报警值（假设报警值为10欧姆）
//                    byte[] value = new byte[8];
//                    value[0] = (byte) 0x01;
//                    value[1] = (byte) 0x06;
//                    value[2] = (byte) 0x00;
//                    value[3] = (byte) 0x03;
//                    value[4] = (byte) 0x00;
//                    value[5] = (byte) 0x05;
//                    value[6] = (byte) 0xF9;
//                    value[7] = (byte) 0xCD;
//                    byte[] value = new byte[]{0x01,0x03,0x00,0x01,0x00,0x01,0xD5,0xCA};
            ClientManager.getClient().write(mBleDevice.getBluetookthAddress(), mService, mCharacter,
                    value, mWriteRsp);
        }

        private void initData() {

        }

        @Override
        public Builder setGravity(int gravity) {
            switch (gravity) {
                // 如果这个是在中间显示的
                case Gravity.CENTER:
                case Gravity.CENTER_VERTICAL:
                    // 不显示取消按钮
                    setCancel(null);
                    // 重新设置动画
                    setAnimStyle(BaseDialog.ANIM_SCALE);
                    break;
                default:
                    break;
            }
            return super.setGravity(gravity);
        }

        @Override
        public Builder addOnDismissListener(@NonNull BaseDialog.OnDismissListener listener) {
            return super.addOnDismissListener(listener);
        }

        /**
         * 销毁,释放资源
         */
        @Override
        public void dismiss() {
            super.dismiss();
        }

        public Builder setBleDevice(BleDeviceListApi.Bean bleDevice) {
            this.mBleDevice = bleDevice;
            return this;

        }

        public Builder setData(TaskDetailStepApi.Bean taskPowerResult) {
            this.mTaskPowerResult = taskPowerResult;
            return this;
        }

        public Builder setCancel(@StringRes int id) {
            return setCancel(getString(id));
        }

        public Builder setCancel(CharSequence text) {
//            mBleOptStatusButton.setText(text);
            return this;
        }

        public Builder setAutoDismiss(boolean dismiss) {
            mAutoDismiss = dismiss;
            return this;
        }

        @SuppressWarnings("rawtypes")
        public Builder setListener(OnListener listener) {
            mListener = listener;
            return this;
        }

        @SingleClick
        @Override
        public void onClick(View view) {
            if (mAutoDismiss) {
                ClientManager.getClient().disconnect(mBleDevice.getBluetookthAddress());
                ClientManager.getClient().unregisterConnectStatusListener(mBleDevice.getBluetookthAddress(), mConnectStatusListener);
                dismiss();
            }

            if (view == mBleOptStatusButton) {
                if (mListener == null || TextUtils.isEmpty(stepStatus)) {
                    return;
                }
                ClientManager.getClient().disconnect(mBleDevice.getBluetookthAddress());
                ClientManager.getClient().unregisterConnectStatusListener(mBleDevice.getBluetookthAddress(), mConnectStatusListener);
                Integer stepValue = mTaskPowerResult.getEquipType() == 3 ? Integer.parseInt(stepStatus) : 0;
                mListener.onSelected(getDialog(), 0, stepValue);
            } else if (view == mBtnBleOptCancel) {
                if (mListener == null) {
                    return;
                }
                ClientManager.getClient().disconnect(mBleDevice.getBluetookthAddress());
                ClientManager.getClient().unregisterConnectStatusListener(mBleDevice.getBluetookthAddress(), mConnectStatusListener);
                mListener.onCancel(getDialog());
            } else if (view == mBtnBleOptReconnect) {
                // 重新读值
                writeForBleToDevices();
            }
        }

        /**
         * {@link View.OnLayoutChangeListener}
         */
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            // 这里一定要加延迟，如果不加在 Android 9.0 上面会导致 setLayoutParams 无效
            post(this);
        }

        @Override
        public void run() {

        }

        /**
         * 获取屏幕的高度
         */
        private int getScreenHeight() {
            Resources resources = getResources();
            DisplayMetrics outMetrics = resources.getDisplayMetrics();
            return outMetrics.heightPixels;
        }
    }

    public interface OnListener<T> {

        /**
         * 选择条目时回调
         */
        void onSelected(BaseDialog dialog, int position, T t);

        /**
         * 点击取消时回调
         */
        default void onCancel(BaseDialog dialog) {
        }
    }

    private static byte[] getWriteData() {

        String s1 = "010300060001640B";

        String crc = getCRC(s1);

        Log.d("bobowa", "s4=" + s1);

        return hexStringToBytes(s1 + crc);

    }

    /**
     * 字符串转换为16进制字符串
     * <p>
     * 设备号转hex命令
     *
     * @param s
     * @return
     */

    public static String stringToHexString(String s) {

        String str = "";

        for (int i = 0; i < s.length(); i++) {

            int ch = s.charAt(i);

            String s4 = Integer.toHexString(ch);

            str = str + s4;

        }

        return str;

    }

    public static String getCRC(String data) {

        data = data.replace(" ", "");

        int len = data.length();

        if (!(len % 2 == 0)) {

            return "0000";

        }

        int num = len / 2;

        byte[] para = new byte[num];

        for (int i = 0; i < num; i++) {

            int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);

            para[i] = (byte) value;

        }

        return getCRC(para);

    }

    public static String getCRC(byte[] bytes) {

//CRC寄存器全为1

        int CRC = 0x0000ffff;

//多项式校验值

        int POLYNOMIAL = 0x0000a001;

        int i, j;

        for (i = 0; i < bytes.length; i++) {

            CRC ^= ((int) bytes[i] & 0x000000ff);

            for (j = 0; j < 8; j++) {

                if ((CRC & 0x00000001) != 0) {

                    CRC >>= 1;

                    CRC ^= POLYNOMIAL;

                } else {

                    CRC >>= 1;

                }

            }

        }

//结果转换为16进制

        String result = Integer.toHexString(CRC).toUpperCase();

        if (result.length() != 4) {

            StringBuffer sb = new StringBuffer("0000");

            result = sb.replace(4 - result.length(), 4, result).toString();

        }

//交换高低位

        return result.substring(2, 4) + result.substring(0, 2);

    }

    /**
     * String转换成每2位的数组
     *
     * @param hexString
     * @return
     */

    public static byte[] hexStringToBytes(String hexString) {

        Log.d("bobowa", "hexStringToBytes=" + hexString);

        if (hexString == null || hexString.equals("")) {

            return null;

        }

        hexString = hexString.toUpperCase();

        int length = hexString.length() / 2;

        char[] hexChars = hexString.toCharArray();

        byte[] d = new byte[length];

        for (int i = 0; i < length; i++) {

            int pos = i * 2;

            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }

        return d;

    }

    public static byte charToByte(char c) {

        return (byte) "0123456789ABCDEF".indexOf(c);

    }
    /* *

     * Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(int)

     *来转换成16进制字符串。

     * @param src byte[] data

     * @return hex string

     */

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}